home *** CD-ROM | disk | FTP | other *** search
- How to build a shadowmaster module.
-
-
- *** Quick Start for SAS C programmers:
-
- Doing a graphics module is relatively easy. Copy the
- "source/savers/black.c" source to the name you've chosen, change the
- colorspec, Title, Screen and Window tags as appropriate, and then put
- your graphics code in the routine "dographics". Dographics is called
- with screen and window opened as you specified, and the raster set to
- color 0. Build your blanker, and run it from the CLI to test it. Use
- CTRL-C to exit.
-
-
- A utility module is somewhat harder. Use the template
- "source/savers/guard.c" as a basis, replacing the template and the
- routine "doutility" as needed. If you're going to do a simple utility
- that just starts a single blanker and then waits for the CTRL-C, your
- routine should just return the command string. If your utility wants
- to wait for other things (timeouts, etc) or wants to do something
- other than exit on keyboard input, you need to compile with -dLOOPS.
- In this case, doutility's argument is TRUE the first time after the
- utility is started, and you should just hand back the command string.
- After the command is launched, doutility is called with a FALSE
- argument. It should then wait for whatever events it wishes, then
- return the string for the next command to be run. For either case,
- returning a NULL pointer will cause the utility to exit.
-
- NOTE: Your routine (dographics or doutility) must RETURN, and not call
- exit.
-
- For more information, see the source files black.c, guard.c,
- savermain.h and utillitymain.h in the savers directory.
-
- If you aren't using SAS C, you can try to compile the above templates
- without a do routine, and then link in with an appropriate routine
- from your favorite language. However, it's probably better to write
- the interface code from scratch, using the appropriate main.h files as
- a guide.
-
-
- *** The Interface Specification
-
- A saver module is told to start by being executed normally. It is told
- that it should stop by being sent a SIGBREAKF_CTRL_C signal. This
- means that doing graphics modules - that only need to do the client
- half of the interface - is relatively easy. Almost any command that
- can be run from the CLI and stopped with a CTRL-C can be used. The
- templates for SAS C are tweaked to be small, but that's all that is
- special about them.
-
- On the server side, things are much more complicated. You can't just
- launch your client module, and blithely wait for the event that means
- they should exit and send them a CTRL-C. If they have exited
- beforehand, your signal could cause the system to crash. Further, your
- client may (for its own reasons) decide to ignore your signal, and not
- exit. You must not start another client until it has exited. Because of
- this, you need to find out when the client exits.
-
- Fortunately, 2.0 provides a perfect facility for this. pr_ExitCode has
- been added to the process structure, and is run when the process
- exits. Unfortunately, I've not been able to get anyone at CBM to state
- that it's safe to send a signal at anytime before this code exits, but
- testing shows that the code runs with the same Task structure as is
- created by CreateNewProc with the tag NP_ExitCode used to set
- pr_ExitCode. Depending on this code to signal the exit should not
- create any race conditions.
-
- The standard used in the templates is that a global variable holds a
- pointer to the client Task structure, and pr_ExitCode sets that
- pointer to NULL, then sends a signal to the server task (with a
- pointer in a second global) to indicate that it has exited, and the
- server should do whatever it feels needs to be done in that case.
-
- Note that the Task structure pointer is accessed by multiple tasks,
- and is used to communicate between them. Because of the dangers
- inherent in misreading the value of this variable, the changes to it
- and the attempts to read it must be locked from mutual access. A
- SignalSemaphore is used for this.
-
-
- *** Configuration
-
- The configuration sytem has two types of objects in it, utility module
- preferences editors, and saver module configuration programs.
- Configuration programs should open a window at 0,11 with the gadgets
- appropriate for that saver module, including a way of aborting with no
- exit. After the user indicates they wish to use the selected
- configuration, the configuration program should write a line to
- standard output that can be used to invoke it. Put in all keywords,
- and don't assume that the module will live in a specific directory. If
- no changes are made, don't write anything to standard output.
-
- Utility modules all use preferences editors. The only allowable start
- switch is "FROM", indicating a preferences file to use other than the
- defaults (generally, env:shadowmaster/modulename.prefs). They should
- be AUISG compliant and provide appropriate facilities for selecting,
- configuring and testing the next module in the chain.
-
- To make this task somewhat easier, the file source/config/prefs.c
- provides a "startup" module for building preferences editors. The user
- code must provide the following external variables, initialized to
- approiate values:
-
- int windowheight ; /* Height to open the window to */
- int windowwidth ; /* Width to open the window to */
- char *basename ; /* env:basename/appname.prefs */
- char *appname ; /* is the default prefs file */
- char *errname ; /* error reports look like errname: text */
-
- You must also provide the following functions for prefs to call:
-
- int SaveFile(char *) ; /* Save current preferences to named file */
- int LoadFile(char *) ; /* Load preferences from named file */
- int Undo(void) ; /* Undo last action */
- int Defaults(void) ; /* Reset to defaults */
- int UserGadgets(struct Gadget *ng,/* Add user gadgets to window */
- struct NewGadget *gad) ;
- void CleanUp(int) ; /* Cleans up before exit */
-
- The Undo and Defaults return TRUE to cause an immediate exit, but
- should probably always return FALSE.
-
- SaveFile and LoadFile return the success of the operation asked for.
-
- Cleanup is passed a TRUE if the user exited with changes to the env:
- or envarc: preferences files, false otherwise.
-
- UserGadets adds the editor-specific gadgets, and returns FALSE if it
- fails. ng is the newgadget structure used to set up the bottom row of
- gadgets. You can (and should) use ng_TextAttr from it, and can depend
- on ng_TopEdge being the top edge of the gadgets for placing your
- gadgets. The created gadgets should have ng_UserData set to point at
- int (*)(struct Gagdet *, UWORD) functions to handle the gadgets. They
- are called when that gadget is selected by the user, with the gadget
- pointed to by the first argument, and the IntuiMessage Code field as
- the second argument. gad is the last gadget created on ng, for
- passing to CreateGadget. These gadgets should return TRUE if the
- editor should exit immediately (in which case CleanUp is called from
- the startup code), and FALSE otherwise. Always returning FALSE is
- probably the correct behavior.
-
- Note that the Defaults, Undo, LoadFile and SaveFile cannot depend on
- window being open, and should check to see if it is NULL before trying
- to use it. If it is open, the gadgets will be in place, and should be
- updated/referenced as needed by all function. In particular,
- GT_SetGadgetAttrs should be called to change the values of these
- objects, and the value should be read from text/integer gadgets before
- saving it, as it is possible for the user to change them without your
- function being called.
-
- Prefs.c provides the following externals to your preferences editor:
-
- extern struct Window *window ; /* The editor window */
- extern USHORT __far BusyPointerData[] ; /* A 2.0 busy wait pointer */
- extern void dowbmessage(char *) ; /* Error reporting routine */
-
- See /source/config/guard.c for an example of using these interface.
-